#!/usr/bin/env python
# -*- coding: utf-8 -*-

import Singleton
import Robot
import ot_pb2
import IL.DataSource.Market
import IL.DataSource.Container
import IL.DataSource.PreMktContainer
from pageType import *
import base_pb2
import stock_trade_pb2


@Singleton.singleton
class Trade():
    def __init__(self):
        self.robot = Robot.Connection()
        self.market = IL.DataSource.Market.MarketSource()
        self.container = IL.DataSource.Container.Memory()
        self.preMkt = IL.DataSource.PreMktContainer.Memory()
        self.trade_id = ''
        self.trade_ip = ''

    def set_trade_id_ip(self, trade_id, trade_ip):
        self.trade_id = trade_id
        self.trade_ip = trade_ip

    def SingleOrder(self, function, code, price, qty, bs_flag,  policyID, instrument_type=0x20, type=base_pb2.CMD_SINGLE_ORDER_REQ):
        msg = stock_trade_pb2.SingleOrderReq()
        msg.market = self.market.getStockCodeIsSH(code)
        msg.code = code
        msg.price = price
        msg.qty = qty
        msg.bs_flag = bs_flag
        msg.trader_id = self.trade_id
        msg.trader_ip = self.trade_ip
        msg.instrument_type = instrument_type
        msg.policy_id = policyID
        self.robot.send(type, msg, function)

    def Login(self, function):
        msg = base_pb2.LoginReq()
        msg.type = 0
        msg.version = base_pb2.MAJOR << 16 or base_pb2.MINOR
        msg.trader_id = self.trade_id
        self.robot.send(base_pb2.CMD_LOGIN_REQ, msg, function)

    def SingleCancel(self, function, order_no, market, type=base_pb2.CMD_SINGLE_WITHDRAWAL_REQ):
        msg = stock_trade_pb2.SingleCancelReq()
        msg.order_no = order_no
        msg.market = market
        msg.trader_id = self.trade_id
        msg.trader_ip = self.trade_ip
        self.robot.send(type, msg, function)

    def get_CompleteTradeDetail(self, variety=None, market=None, policyID=None, idAdress=None, terminal=None,
                                ot_stock=None, ot_etf_trade=None, ot_etf=None, ot_reverse=None, ot_other=None,
                                tt_common=None, tt_cancel=None, tt_waste=None,
                                stockCode=None, etfCode=None):
        ret = self.container.get_CompleteTradeDetail(variety, market, policyID, idAdress, terminal, ot_stock, ot_etf_trade,
                                                     ot_etf, ot_reverse, ot_other, tt_common, tt_cancel, tt_waste,
                                                     stockCode, etfCode)
        return ret

    def get_EasyTradeDetail(self, variety=None, terminal=None):
        ret = self.container.get_EasyTradeDetail(variety, terminal)
        return ret

    def get_OrderList(self, variety=None, code=None, ip=None):
        ret = self.container.get_OrderList(variety, code, ip)

        seq = 1
        listRet = list()
        for item in ret:
            retListItem = [seq, item.stock_id, item.stock_name, item.bs_flag, item.price,
                           item.state, item.volume, item.knock_volume, item.order_request_time,
                           item.order_no, "未知-撤单标示", item.trader_id, item.trader_ip]
            listRet.append(retListItem)
            seq += 1
        return listRet

    def get_ReplaceComplement(self, etfcode):
        ret = self.preMkt.get_ETF_DataList(etfcode)
        listRet = list()
        seq = 1
        for item in ret:
            stock_market = self.market.get(item.stock_id)
            stock_position = self.container.get_Position_code(item.stock_id)
            qk = item.execute_qty - stock_position.position
            if qk < 0:
                qk = 0
            listRet.append([seq, item.stock_id, item.stock_name, stock_market.status, qk, qk*stock_market.match])
            seq += 1

        return listRet

    def get_Position(self, OnlyETF=False, HideZeroPosition=False, SearchCodeList=[]):
        ret = self.container.get_Position()
        listRet = list()
        for item in ret:
            flags = [False, False, False]
            code_info = self.market.getCodeInfo(item.stock_id)
            if OnlyETF:
                if (code_info.type >= 0x20 and code_info.type < 0x30):
                    flags[0] = True
                else:
                    flags[0] = False
            else:
                flags[0] = True

            if HideZeroPosition:
                if item.volume != 0:
                    flags[1] = True
                else:
                    flags[1] = False
            else:
                flags[1] = True

            if SearchCodeList:
                for i in SearchCodeList:
                    if str(item.stock_id).find(str(i)) != -1:
                        flags[2] = True
                        break
            else:
                flags[2] = True


            try:
                can_sell_market_posit = item.market_value/item.volume*item.can_sell_volume
            except:
                can_sell_market_posit = 0

            if flags[0] and flags[1] and flags[2]:
                listRet.append([item.stock_id, item.stock_name, item.volume, item.market_value,
                                item.can_sell_volume, can_sell_market_posit,
                                item.etf_can_redeem_volume, item.etf_cur_purchase_addition, item.etf_cur_redeem_reduction])

        return listRet

    def get_BasketUnfinished(self):
        ret = self.container.get_BasketUnfinished()
        listRet = list()
        for item in ret:
            listRet.append([item.code, item.volume, item.bsflag, item.money, item.rate, item.strategyID])

        return listRet

    def get_AccountPosition(self):
        try:
            ret = self.container.get_Position()
            listRet = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
            for i in ret:
                if i.market:
                    listRet[4] += i.market_value
                else:
                    listRet[5] += i.market_value
            money = self.container.get_Money()
            listRet[0] = money['usable'] / 10000.0
            listRet[2] = money['freeze_buy'] / 10000.0
            listRet[3] = money['freeze_sell'] / 10000.0
            listRet[4] /= 10000.0
            listRet[5] /= 10000.0
            listRet[9] = listRet[4] + listRet[5]
            return listRet
        except KeyError:
            return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        except:
            import logging
            logging.warning('Interface:Trade:get_AccountPosition:Error')
            return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

    def get_Money(self):
        ret = self.container.get_Money()
        return ret